ScrapboxからGoogle APIのAccess Tokenを取得する
/icons/hr.icon
/icons/hr.icon
only Firefox
認証情報の取得手順
1. Authorization Codeを取得する
code:js
(async () => {
const {openAuthWindow} = await import('/api/code/programming-notes/ScrapboxからGoogle_APIのAccess_Tokenを取得する/script.js');
const {CLIENT_ID} = await import('/api/code/takker-memex/Google_API_for_Scrapbox/script.js');
})();
code:script.js
window.open(https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=${clientId}&redirect_uri=${redirectURI}&access_type=offline&scope=${scopes.join('%20')});
}
code:script.d.ts
export function openAuthWindow(props: {
clientId: string;
redirectURI: string;
scopes: string[];
}): void;
認証した後にredirectされるページのURL parametercodeに入っている文字列がAuthorization Codeである
2. Authorization CodeとAccess Tokenとを交換する
code:js
(async () => {
const {getTokens} = await import('/api/code/programming-notes/ScrapboxからGoogle_APIのAccess_Tokenを取得する/script.js');
const {CLIENT_ID, CLIENT_SECRET} = await import('/api/code/takker-memex/Google_API_for_Scrapbox/script.js');
console.log(await getTokens({
clientId: CLIENT_ID,
clientSecret: CLIENT_SECRET,
authorizationCode: '4/0AY0e-g4G87VG-LBMMIQPSFFRBiRIwnNPTm__KYXlhym2PcMoza6VufT5gNwQDUQ8oAXHCQ',
}));
})();
code:script.js
// parametersを組み立てる
const body = new URLSearchParams();
body.append('client_id', clientId);
body.append('client_secret', clientSecret);
body.append('code', authorizationCode);
body.append('grant_type', 'authorization_code');
body.append('redirect_uri', redirectURI);
body.append('access_type', 'offline');
// access tokenを取得する
const res = await fetch(https://oauth2.googleapis.com/token, {
method: 'POST',
body,
});
return await res.json();
}
code:script.d.ts
export function getTokens(props: {
clientId: string;
clientSecret: string;
redirectURI: string;
authorizationCode: string;
}): Promise<{
error_description: string;
} | {
access_token: string;
refresh_token?: string;
scope: string;
expires_in: number;
token_type: 'Bearer';
}>;
Access Tokenの有効期限が切れたら、Refresh Tokenで更新する
Access Tokenの有効期限を確認する
code:script.js
export async function verifyToken(accessToken) {
const res = await fetch(https://www.googleapis.com/oauth2/v3/tokeninfo?access_token=${accessToken});
return await res.json();
}
code:script.d.ts
export function verifyToken(accessToken: string): Promise<{
error_description: string;
} | {
azp: string;
aup: string;
scope: string;
exp: string; // 中身は数値
expires_in: string; // 中身は数値
access_type: 'online' | 'offline';
}>;
Access Tokenを更新する
code:script.js
export async function refreshToken({clientId, clientSecret, refreshToken}) {
// parametersを組み立てる
const body = new URLSearchParams();
body.append('client_id', clientId);
body.append('client_secret', clientSecret);
body.append('grant_type', 'refresh_token');
body.append('refresh_token', refreshToken);
// access tokenを更新する
const res = await fetch(https://oauth2.googleapis.com/token, {
method: 'POST',
body,
});
return await res.json();
}
code:script.d.ts
export function refreshToken(props: {
clientId: string;
clientSecret: string;
refreshToken: string;
}): Promise<{
error_description: string;
} | {
access_token: string;
scope: string;
expires_in: number;
token_type: 'Bearer';
}>;
手動操作なしに、auth tokenを取得する方法を探ってみる
2021-06-06 12:05:32 Uncaught DOMException: Permission denied to access property "searchParams" on cross-origin objectがでて解析できなかった
文字列解析ならできそうなので、そっちでやるか。
だめだった
何をするにせよ、window objectにアクセスするのがCORS違反になる
遷移前はエラーが出まくるのでtry...catchで握りつぶす
code:js
(async () => {
const {getAuthToken} = await import('/api/code/takker/ScrapboxからGoogle_APIのAccess_Tokenを取得する/script.js');
const {CLIENT_ID, CLIENT_SECRET} = await import('/api/code/takker-memex/Google_API_for_Scrapbox/script.js');
console.log(await getAuthToken({
clientId: CLIENT_ID,
clientSecret: CLIENT_SECRET,
}));
})();
code:script.js
export async function getAuthToken({clientId, clientSecret, scopes}) {
const popup = window.open(https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=${clientId}&redirect_uri=${redirectURI}&scope=${scopes.join('%20')});
const pending = new Promise((resolve, reject) => {
const timer = setInterval(() => {
if (popup.location.host !== 'scrapbox.io') return;
clearInterval(timer);
console.log(popup.location.search);
const params = new URLSearchParams(popup.location.search);
const code = params.get('code');
const error = params.get('error');
popup.close();
if (error) {
reject(error);
return;
}
resolve(code);
}, 1000);
});
const authorizationCode = await pending;
return await getTokens({clientId, clientSecret, authorizationCode, redirectURI});
}
References